﻿using System;
using System.Web;
using System.Net.WebSockets;
using System.Web.WebSockets;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace aop_cache
{
    public class WebSocketHandler : IHttpHandler
    {
        private const int MaxBufferSize = 64 * 1024;

        public void ProcessRequest(HttpContext context)
        {
            try
            {

                //AcceptWebSocketRequest(Func<AspNetWebSocketContext, System.Threading.Tasks.Task> userFunc); 方法
                //用一个指定的方法,接收一个 System.Web.WebSockets.AspNetWebSocket 请求。这个
                //请求不是一个 System.Web.WebSockets.AspNetWebSocket 请求。
                context.AcceptWebSocketRequest(async wsContext =>
                {
                    try
                    {
                        byte[] receiveBuffer = new byte[MaxBufferSize];

                        // 初始化 System.ArraySegment<T> 结构的新实例，该结构用于分隔指定数组中的所有元素。
                        ArraySegment<byte> buffer = new ArraySegment<byte>(receiveBuffer);

                        //返回 : 当前的 System.Web.WebSockets.AspNetWebSocket 实例。
                        WebSocket socket = wsContext.WebSocket;
                        string userString;

                        if (socket.State == WebSocketState.Open)
                        {
                            // 链接建立起来后通知一下
                            var announceString = "EchoWebSocket Connected at: " + DateTime.Now.ToString();

                            //ArrarSegment<T> : 分隔一维数组的一部分。
                            ArraySegment<byte> outputBuffer2 = new ArraySegment<byte>(Encoding.UTF8.GetBytes(announceString));

                            //通过 WebSocket 连接异步发送数据。
                            await socket.SendAsync(outputBuffer2, WebSocketMessageType.Text, true, CancellationToken.None);
                        }

                        // 当 WebSocket处于打开状态时, 轮询客户端发送来的数据
                        while (socket.State == WebSocketState.Open)
                        {

                            //从 WebSocket 链接中异步接收数据
                            WebSocketReceiveResult receiveResult = await socket.ReceiveAsync(buffer, CancellationToken.None);

                            if (receiveResult.MessageType == WebSocketMessageType.Close)
                            {
                                // public abstract Task CloseAsync(WebSocketCloseStatus closeStatus, string statusDescription, CancellationToken
                                //                                           cancellationToken) : 关闭 WebSocket  连接,使用关闭握手中定义的 WebSocket协议
                                await socket.CloseAsync(
                                                                receiveResult.CloseStatus.GetValueOrDefault(),
                                                                receiveResult.CloseStatusDescription,
                                                                CancellationToken.None);
                                return;
                            }

                            //显示 WebSocket  收到的字节数。
                            int offset = receiveResult.Count;

                            while (receiveResult.EndOfMessage == false)
                            {
                                //在异步 WebSocket 连接中接收的数据。
                                receiveResult = await socket.ReceiveAsync(new ArraySegment<byte>(receiveBuffer,
                                                                           offset, MaxBufferSize - offset), CancellationToken.None);
                                offset += receiveResult.Count;
                            }

                            //判断当前收到的消息是一个  utf - 8 消息 还是一个 二进制的消息。
                            if (receiveResult.MessageType == WebSocketMessageType.Text)
                            {
                                string cmdString = Encoding.UTF8.GetString(receiveBuffer, 0, offset); //将指定字节数组中的一个字节序列解码为一个字符串。

                                userString = cmdString;
                                userString = "You said: \"" + userString + "\"";

                                ArraySegment<byte> outputBuffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userString));

                                //通过 WebSocket 对象 异步发送数据
                                await socket.SendAsync(outputBuffer, WebSocketMessageType.Text, true, CancellationToken.None);
                            }
                            else if (receiveResult.MessageType == WebSocketMessageType.Binary)
                            {
                                userString = String.Format("binary message received, size={0} bytes", receiveResult.Count);

                                ArraySegment<byte> outputBuffer = new ArraySegment<byte>(Encoding.UTF8.GetBytes(userString));

                                await socket.SendAsync(outputBuffer, WebSocketMessageType.Text, true, CancellationToken.None);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        //System.Diagnostics.Trace.WriteLine(ex);
                    }
                });
            }
            catch (Exception ex)
            {
                //System.Diagnostics.Trace.WriteLine(ex);
                context.Response.StatusCode = 500;
                context.Response.StatusDescription = ex.Message;
                context.Response.End();
            }
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}